package contatos.presenter;

import contatos.collection.XML;
import contatos.collection.Contatos;
import contatos.model.Contato;
import contatos.patterns.observer.Observer;
import contatos.patterns.strategy.IOrdernarStrategy;
import contatos.patterns.strategy.OrdenarPorNome;
import contatos.patterns.strategy.OrdenarPorOperadora;
import contatos.patterns.strategy.OrdenarPorTelefone;
import contatos.patterns.strategy.OrdenarPorUF;
import contatos.view.ListaContatosView;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.xml.sax.SAXException;

/**
 *
 * @author felipe secato
 */
public final class ListarContatosPresenter implements Observer {

    private DefaultTableModel tm;
    private Contatos contatos;
    private ListaContatosView view;
    private IOrdernarStrategy ordenarStrategy;

    public ListarContatosPresenter() {
        try {
            view = new ListaContatosView();
            Object colunas[] = {"Nome", "Telefone"};

            //definindo o table model
            tm = new DefaultTableModel(colunas, 0) {
                @Override
                public boolean isCellEditable(int row, int column) {
                    //desabilitando a edição de celulas
                    return false;
                }
            };

            //obtendo a instancia da classe de persistencia (singleton)
            contatos = Contatos.getInstancia();

            //adicionando este observador a lista do subject (observer)
            contatos.registryObserver(this);

            //carregando as pessoas
            contatos.carregaPessoas();

            //preenchendo o table model
            carregaPessoas(contatos.getTreeSet());

            //Listeners
            view.getBtnAdicionar().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    incluiPessoa();
                }
            });

            view.getBtnVisualizar().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    alteraPessoa();
                }
            });

            view.getBtnExcluir().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    excluirPessoa();
                }
            });

            view.getCbOrdenar().addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ordenarLista();
                }
            });

            view.getChbCrescente().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    ordenarLista();
                }
            });

            view.getCbListarIncompletos().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    carregaPessoas(contatos.getTreeSet());
                }
            });

            view.getBtnOpcoes().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    view.getBtnOpcoes().add(view.getJpMenu());
                    view.getJpMenu().show(view,
                            view.getBtnOpcoes().getBounds().x,
                            view.getBtnOpcoes().getBounds().y + 2 * view.getBtnOpcoes().getBounds().height);
                }
            });

            view.getMenuImportar().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    XML xmlUtil = new XML();
                    try {
                        xmlUtil.importarXML(contatos.getTreeSet());
                    } catch (ParserConfigurationException ex) {
                        Logger.getLogger(ListarContatosPresenter.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (SAXException ex) {
                        Logger.getLogger(ListarContatosPresenter.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IOException ex) {
                        Logger.getLogger(ListarContatosPresenter.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });
            
            view.getMenuExportar().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                     XML xmlUtil = new XML();
                    try {
                        xmlUtil.exportarXML(contatos.getCompletos());
                    } catch (TransformerException ex) {
                        Logger.getLogger(ListarContatosPresenter.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            });

            
            view.getMenuSair().addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });

            view.getTxtPesquisar().addKeyListener(new KeyAdapter() {
                @Override
                public void keyReleased(KeyEvent e) {
                    carregaPessoas(contatos.getTreeSet());
                }
            });

            view.getJtPessoas().setModel(tm);
            view.setVisible(true);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(view, ex.getMessage());
        }

    }

    private void ordenarLista() {
        ArrayList<Contato> lista = new ArrayList<Contato>(contatos.getTreeSet());
        switch (view.getCbOrdenar().getSelectedIndex()) {
            case 1:
                ordenarStrategy = new OrdenarPorNome();
                break;
            case 2:
                ordenarStrategy = new OrdenarPorTelefone();
                break;
            case 3:
                ordenarStrategy = new OrdenarPorUF();
                break;
            case 4:
                ordenarStrategy = new OrdenarPorOperadora();
                break;
            default:
                ordenarStrategy = new OrdenarPorNome();
        }
        ordenarStrategy.ordenar(lista, view.getChbCrescente().isSelected());
        carregaPessoas(lista);
    }

    private void incluiPessoa() {
        new InclusaoContatoPresenter();
    }

    private void alteraPessoa() {
        if (contatoSelecionado() != null) {
            new VisualizaContatoPresenter(contatoSelecionado());
        }
    }

    private void excluirPessoa() {
        if (contatoSelecionado() != null) {
            try {
                int opt = JOptionPane.showConfirmDialog(view, "Deseja realmente excluir este contato?",
                        "Confirmação de exclusão", JOptionPane.YES_NO_OPTION);
                if (opt == 0) {
                    contatos.excluir(contatoSelecionado());
                }
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(view, ex.getMessage());
            }
        }
    }

    private Contato contatoSelecionado() {
        try {
            if (view.getJtPessoas().getSelectedRow() == -1) {
                throw new Exception("Selecione um registro primeiro");
            }
            String nome = (String) view.getJtPessoas().getValueAt(view.getJtPessoas().getSelectedRow(), 0);
            Iterator<Contato> it = contatos.iterator();
            while (it.hasNext()) {
                Contato p = it.next();
                if (p.getNome().equals(nome)) {
                    return p;
                }
            }
            throw new Exception("O registro selecionado não esta na collection");
        } catch (Exception e) {
            JOptionPane.showMessageDialog(view, e.getMessage());
            return null;
        }
    }

    private void carregaPessoas(Collection<Contato> c) {
        tm.setNumRows(0);
        Iterator<Contato> it = c.iterator();
        while (it.hasNext()) {
            Contato p = it.next();
            String pessoa = p.toString();
            String linha[] = pessoa.split(",");
            if (!view.getTxtPesquisar().getText().equals("")) {
                String pesquisa = view.getTxtPesquisar().getText();
                if (p.getNome().toLowerCase().startsWith(pesquisa.toLowerCase())
                        || p.getTelefone().replaceAll("([(-)-])", "").startsWith(pesquisa)) {
                    tm.addRow(new Object[]{linha[0], linha[1]});
                }
            } else {
                if (view.getCbListarIncompletos().isSelected() && linha.length == 2) {
                    tm.addRow(new Object[]{linha[0], linha[1]});
                } else if (!view.getCbListarIncompletos().isSelected() && linha.length == 4) {
                    tm.addRow(new Object[]{linha[0], linha[1]});
                }
            }
        }
        view.getLblTotal().setText("Total: " + tm.getRowCount());
    }

    @Override
    public void update(Contatos pessoas) {
        carregaPessoas(pessoas.getTreeSet());
    }
}
